﻿package org.app.data;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.app.Ports;
import org.app.MyUtils;
import org.app.entities.MyCoordinate;
import org.app.entities.MyNode;
import org.app.original.MyImage;
import org.app.original.improve.MyFormat;

public class MyTree {
	MyNode root;
	int depth;
	int breadth;
	Map<MyNode,MyCoordinate> map=new HashMap();
	public MyTree(){
		root=new MyNode("零0零零0零");
		
		MyNode n1=new MyNode("一");
		MyNode n2=new MyNode("二");
		MyNode n3=new MyNode("三");
		MyNode n4=new MyNode("四");
		MyNode n5=new MyNode("五");
		MyNode n6=new MyNode("六");
		MyNode n7=new MyNode("七");
		MyNode n8=new MyNode("八");	
		MyNode n9=new MyNode("九");
		MyNode n10=new MyNode("十");
		
		root.add(new MyNode[]{n1,n2,n3});
		
		n2.add(new MyNode[]{n4,n5,n6});
		n4.add(new MyNode[]{n8,n9});
		n6.add(n7);
		
		
		n3.add(n10);
	}
	
	public static void main(String[] args){
		MyTree tree=new MyTree();
		tree.toMap();
		tree.toArray();
		BufferedImage img=tree.toImage();
		new MyImage().save(img,"tree.jpg");
		String json=new MyFormat().decrypt(tree.getRoot());
		System.out.println(json);
	}
	
	public void fromJSON(String json){
		
	}
	
	/**
	 * 根据树型结构 构建矩阵
	 * map 记录记录矩阵的节点坐标
	 */
	public void toMap(){
		map.put(root,new MyCoordinate());
		addChildren(root);
		//toArray();
		
		System.out.println(this.depth+","+this.breadth);
		MyUtils.show(map);
	}
	
	
	/**
	 * 添加子节点 后 修改矩阵坐标
	 * 遍历树型结构  添加子节点 
	 * 当前节点node,根据节点的个数 ，则offset=size/2为当前节点的偏移量（矩阵y坐标）,子节点x坐标为x+1,y坐标范围为 （y,y+size）
	 * 而此时矩阵坐标将相应变化：（由于是树型的先序遍历，添加子节点只对  坐标>=node的坐标 产生影响）
	 * 即 矩阵中与node 在同一列的y=y+offset;在node右侧（坐标>y）,若其坐标y轴>最后一个子节点的y,则更新为col=y+size
	 * 同时更新当前矩阵的大小（若有子节点，当深度<row+1或广度<子节点的最大y轴时更新）
	 * @param node
	 */
	public void addChildren(MyNode node){
		int size=node.getChildNum();
		int offset=size/2;
		MyCoordinate coordinate=map.get(node);
		int col=coordinate.getLongitude();
		int row=coordinate.getLatitude();
		
		Set<Entry<MyNode, MyCoordinate>> set=map.entrySet();
		for(Entry<MyNode,MyCoordinate> entry:set){
			MyCoordinate coord=entry.getValue();
			int y=coord.getLongitude();
			if(y==col){
				int c=y+offset;
				coord.setLongitude(c);
			}else if(y>col){
				//int c=y+offset;
				//if(c<=col+size-1){
			//		c=col+size;
			//	}
				int c=y+size;
				coord.setLongitude(c);
			}
		}
		
		addChildren(row,col,node.getChildren());
		List<MyNode> child=node.getChildren();
		for(MyNode n:child){
			addChildren(n);
		}
	}
	
	public void addChildren(int row,int col,List<MyNode> child){
		int size=child.size();
		int r=row+1;
		for(int i=0;i<size;i++){
			MyNode key=child.get(i);
			MyCoordinate value=new MyCoordinate(r,col+i);
			map.put(key, value);
		}
		
		if(size>0)
		setBorder(r,col+size-1);
		else{
			setBorder(row,col);
		}
	}

	private void setBorder(int row,int col){
		if(this.depth<row)depth=row;
		if(this.breadth<col)breadth=col;
	}
	
	public void toArray(){//test 当前矩阵
	//	MyNode[][] array=new MyNode[this.depth+1][this.breadth+1];
		int row=this.getDepth();
		int col=this.getBreadth();
		final int[][] matrix=new int[row][col];
		
		this.visit(root, new Ports(){

			@Override
			public Object execute(Object obj) {
				// TODO Auto-generated method stub
				if(obj instanceof MyNode){
					MyNode node=(MyNode)obj;
					MyCoordinate coord=getCoordinate(node);
					int row=coord.getLatitude();
					int col=coord.getLongitude();
					matrix[row][col]=1;
				}
				return null;
			}
			
		});
		
		
		MyUtils.show(matrix);
		
	}
	
	public BufferedImage toImage(){
		final int unit=48;
		int w=(getBreadth()*2+1)*unit;
		int h=(getDepth()*2+1)*unit;
		BufferedImage img=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
		final Graphics2D g2d=img.createGraphics();
		
		
		this.visit(root, new Ports(){

			
			public Object execute(Object obj) {
				// TODO Auto-generated method stub
				if(obj instanceof MyNode){
					int h=unit;
					int w=unit/2*3;
					MyNode node=(MyNode)obj;
					MyCoordinate coord=getCoordinate(node);
					int row=coord.getLatitude();
					int col=coord.getLongitude();
					
					//增加边框 x,y 距四周+1单位
					int x=(col*2+1)*unit; //col*2*unit
					int y=(row*2+1)*unit;
					g2d.drawRect(x, y, w, h);////边框
					
					String name=node.getName();
					
					int size=g2d.getFont().getSize();
					
					try {
						
						int offsetx=(w-size*name.getBytes("GBK").length/2)/2;//文本居中时 区分中英文 字符， 中文为两个字节
						
//						while(offsetx<6){
//							size=size*2/3;
//							offsetx=(w-size*name.getBytes("GBK").length/2)/2;
//							g2d.setFont(new Font("Dialog", Font.PLAIN, size));
//							System.out.println(offsetx);
//						}
						
						int offsety=(h-size)/2;
					
						//System.out.println(size+","+x+"."+y+":"+node.getName().getBytes("GBK").length);
					
						//size=g2d.getFont().getSize();
						g2d.drawString(node.getName(), x+offsetx, y+offsety+size);//节点名
						
					} catch (UnsupportedEncodingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					x+=w/2;
					y-=unit/2;
					if(y>unit){
						g2d.drawLine(x, y, x, y+unit/2);  //除根节点外各节点向上半截连线
						
					}
					
					List<MyNode> children=node.getChildren();
					 size=0;
					if((size=children.size())>0){
						MyNode bNode=children.get(0);
						MyNode eNode=children.get(size-1);
						y=getRow(bNode)*unit*2+unit/2;
						int begin=(getColumn(bNode)+1)*unit*2-(w-unit)/2;  
						int end=(getColumn(eNode)+1)*unit*2-(w-unit)/2;    
						g2d.drawLine(begin, y, end, y); //子节点 间连线
						
						g2d.drawLine(x, y, x, y-unit/2); //有叶子节点 的节点向下半截连线 
						
					}
					
				}
				return null;
			}
			
		});
		return img;
	}
	
	

	public int getDepth() {
		return depth+1;
	}

	

	public int getBreadth() {
		return breadth+1;
	}
	
	public MyCoordinate getCoordinate(MyNode node){
		return map.get(node);
	}

	public int getColumn(MyNode node){
		return map.get(node).getLongitude();
	}
	
	public int getRow(MyNode node){
		return map.get(node).getLatitude();
	}

	public Map<MyNode, MyCoordinate> getMap() {
		return map;
	}

	public void setMap(Map<MyNode, MyCoordinate> map) {
		this.map = map;
	}
	
	
	
	public MyNode getRoot() {
		return root;
	}

	public void setRoot(MyNode root) {
		this.root = root;
	}

	public void visit(MyNode node,Ports port){
		port.execute(node);
		
		List<MyNode> children=node.getChildren();
		for(MyNode n:children){
			visit(n,port);
		}
	}
	
}
